/*******************************************************************************
 * Copyright (c) 2004, 2010 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.ui.internal.presentations.defaultpresentation;

import org.eclipse.jface.util.Geometry;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.custom.ViewForm;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.IPropertyListener;
import org.eclipse.ui.internal.dnd.DragUtil;
import org.eclipse.ui.internal.layout.SizeCache;
import org.eclipse.ui.internal.presentations.util.AbstractTabFolder;
import org.eclipse.ui.internal.presentations.util.AbstractTabItem;
import org.eclipse.ui.internal.presentations.util.PartInfo;
import org.eclipse.ui.internal.presentations.util.ProxyControl;
import org.eclipse.ui.internal.presentations.util.StandardSystemToolbar;
import org.eclipse.ui.internal.presentations.util.TabFolderEvent;
import org.eclipse.ui.internal.util.Util;

/**
 * @since 3.1
 */
public class NativeTabFolder extends AbstractTabFolder {

	private TabFolder control;
	private ViewForm viewForm;
	private StandardSystemToolbar systemToolbar;
	private CLabel title;
	private ProxyControl topCenter;
	private SizeCache topCenterCache;

	private Listener selectionListener = new Listener() {
		public void handleEvent(Event e) {
			fireEvent(TabFolderEvent.EVENT_TAB_SELECTED, getTab(e.item));
		}
	};

	private IPropertyListener systemToolbarListener = new IPropertyListener() {

		public void propertyChanged(Object source, int propId) {
			Point location;

			if (propId == TabFolderEvent.EVENT_PANE_MENU) {
				location = getPaneMenuLocation();
			} else {
				location = new Point(0, 0);
			}

			fireEvent(propId, getSelection(), location);
		}

	};

	public NativeTabFolder(Composite parent) {
		control = new TabFolder(parent, SWT.BOTTOM);
		control.addListener(SWT.Selection, selectionListener);
		attachListeners(control, false);

		viewForm = new ViewForm(control, SWT.FLAT);
		attachListeners(viewForm, false);
		systemToolbar = new StandardSystemToolbar(viewForm, true, false, true, true, true);
		systemToolbar.addListener(systemToolbarListener);
		viewForm.setTopRight(systemToolbar.getControl());

		topCenter = new ProxyControl(viewForm);
		topCenterCache = new SizeCache();

		title = new CLabel(viewForm, SWT.LEFT);
		attachListeners(title, false);
		viewForm.setTopLeft(title);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.ui.internal.presentations.util.AbstractTabFolder#computeSize
	 * (int, int)
	 */
	public Point computeSize(int widthHint, int heightHint) {
		return new Point(50, 50);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.ui.internal.presentations.util.AbstractTabFolder#add(int)
	 */
	public AbstractTabItem add(int index, int flags) {
		NativeTabItem item = new NativeTabItem(this, index);
		item.getWidget().setData(item);

		return item;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.ui.internal.presentations.util.AbstractTabFolder#layout(boolean
	 * )
	 */
	public void layout(boolean flushCache) {
		super.layout(flushCache);

		Rectangle oldBounds = viewForm.getBounds();
		Rectangle newBounds = control.getClientArea();

		viewForm.setBounds(newBounds);

		if (Util.equals(oldBounds, newBounds)) {
			viewForm.layout(flushCache);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ui.internal.presentations.util.AbstractTabFolder#
	 * getPaneMenuLocation()
	 */
	public Point getPaneMenuLocation() {
		return systemToolbar.getPaneMenuLocation();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.ui.internal.presentations.util.AbstractTabFolder#setState
	 * (int)
	 */
	public void setState(int state) {
		super.setState(state);

		systemToolbar.setState(state);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.ui.internal.presentations.util.AbstractTabFolder#getClientArea
	 * ()
	 */
	public Rectangle getClientArea() {
		Control content = viewForm.getContent();

		if (content == null) {
			return new Rectangle(0, 0, 0, 0);
		}

		return Geometry.toControl(control, DragUtil.getDisplayBounds(content));
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.ui.internal.presentations.util.AbstractTabFolder#getItems()
	 */
	public AbstractTabItem[] getItems() {
		TabItem[] items = control.getItems();

		AbstractTabItem[] result = new AbstractTabItem[items.length];

		for (int i = 0; i < result.length; i++) {
			result[i] = getTab(items[i]);
		}

		return result;
	}

	private AbstractTabItem getTab(Widget item) {
		return (AbstractTabItem) item.getData();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.ui.internal.presentations.util.AbstractTabFolder#setSelection
	 * (org.eclipse.ui.internal.presentations.util.Widget)
	 */
	public void setSelection(AbstractTabItem toSelect) {
		if (toSelect == null) {
			return;
		}

		NativeTabItem tab = (NativeTabItem) toSelect;
		control.setSelection(new TabItem[] { (TabItem) tab.getWidget() });
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.ui.internal.presentations.util.AbstractTabFolder#setSelectedInfo
	 * (org.eclipse.ui.internal.presentations.util.PartInfo)
	 */
	public void setSelectedInfo(PartInfo info) {
		if (!Util.equals(title.getText(), info.title)) {
			title.setText(info.title);
		}
		if (title.getImage() != info.image) {
			title.setImage(info.image);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.ui.internal.presentations.util.AbstractTabFolder#getToolbarParent
	 * ()
	 */
	public Composite getToolbarParent() {
		return viewForm;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.ui.internal.presentations.util.AbstractTabFolder#getTabArea()
	 */
	public Rectangle getTabArea() {

		Rectangle bounds = control.getBounds();

		Rectangle clientArea = control.getClientArea();

		bounds.x = 0;
		bounds.y = 0;
		Geometry.expand(bounds, 0, 0, -(clientArea.height + clientArea.y), 0);

		return Geometry.toDisplay(control.getParent(), bounds);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.ui.internal.presentations.util.AbstractTabFolder#setToolbar
	 * (org.eclipse.swt.widgets.Control)
	 */
	public void setToolbar(Control toolbarControl) {

		if (toolbarControl != null) {
			topCenterCache.setControl(toolbarControl);
			topCenter.setTarget(topCenterCache);
			viewForm.setTopCenter(topCenter.getControl());
		} else {
			topCenterCache.setControl(null);
			topCenter.setTarget(null);
			viewForm.setTopCenter(null);
		}

		super.setToolbar(toolbarControl);
	}

	public Control getControl() {
		return control;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.ui.internal.presentations.util.AbstractTabFolder#isOnBorder
	 * (org.eclipse.swt.graphics.Point)
	 */
	public boolean isOnBorder(Point globalPos) {
		Point localPos = getControl().toControl(globalPos);

		Rectangle clientArea = getClientArea();
		return localPos.y > clientArea.y && localPos.y < clientArea.y + clientArea.height;
	}

	public AbstractTabItem getSelection() {
		TabItem[] sel = control.getSelection();

		if (sel.length == 0) {
			return null;
		}

		return getTab(sel[0]);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.ui.internal.presentations.util.AbstractTabFolder#getContentParent
	 * ()
	 */
	public Composite getContentParent() {
		return viewForm;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.ui.internal.presentations.util.AbstractTabFolder#setContent
	 * (org.eclipse.swt.widgets.Control)
	 */
	public void setContent(Control newContent) {
		viewForm.setContent(newContent);
	}

	public TabFolder getTabFolder() {
		return control;
	}

	void setSelectedTitle(String newTitle) {
		title.setText(newTitle);
	}

	/**
	 * @param image
	 * @since 3.1
	 */
	/* protected */void setSelectedImage(Image image) {
		title.setImage(image);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.ui.internal.presentations.util.AbstractTabFolder#getItem(
	 * org.eclipse.swt.graphics.Point)
	 */
	public AbstractTabItem getItem(Point toFind) {
		return getSelection();
	}

	/**
	 * @param enabled
	 * @since 3.1
	 */
	public void enablePaneMenu(boolean enabled) {
		systemToolbar.enablePaneMenu(enabled);
	}
}
